using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Common;
using Microsoft.TeamFoundation.WorkItemTracking;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Microsoft.TeamFoundation.Controls;
using Microsoft.TeamFoundation.Proxy;

using C1.Win.C1FlexGrid;

namespace Hemi
{
    public partial class QueryForWorkItems : UserControl, IMoveStage
    {
        WorkItemPicker _workItemPicker;
        Project _targetProject;
        ProgressDialog _progressDialog;
        String _invalidMessage;

        public QueryForWorkItems()
        {
            InitializeComponent();

            _progressDialog = new ProgressDialog();
            _progressDialog.StartPosition = FormStartPosition.CenterParent;
        }
      
        #region IMoveStage Members

        string IMoveStage.Name
        {
            get { return "Which Work Items do you want to move?"; }
        }

        string IMoveStage.Description
        {
            get
            {
                return @"
Please select a Team Foundation Server from which to move work items.  In this version, 
work items can only be moved from between projects located on the same logical Team 
Foundation Server.  Work items may be moved between different Team Projects, but all of 
the Team Projects must belong to the same Team Foundation Server.";
            }
        }

        bool IMoveStage.CanTestValidate
        {
            get { return true; }
        }

        string IMoveStage.InvalidMessage
        {
            get { return _invalidMessage; }
        }

        string IMoveStage.ValidMessage
        {
            get { return Properties.Resources.MissingFields_ValidMessage; }
        }

        MoveStageState IMoveStage.State
        {
            get { return MoveStageState.OK; }
        }

        UserControl IMoveStage.UserControl
        {
            get { return this; }
        }

        void IMoveStage.CommitChanges()
        {
            #region Set WorkItemsToMoveSingleton

            MessageBox.Show("+" + _targetProject.Name);
            //
            // This should be the only place where we setup our WorkItemsToMoveSingleton
            // class
            //        
            foreach (C1.Win.C1FlexGrid.Row row in _workItemsFlex.Rows)
            {
                if (row.Index != 0 && (bool)row["move"])
                {
                    WorkItem workItem = (WorkItem)row.UserData;
                    WorkItemMoveInfo moveInfo = new WorkItemMoveInfo(workItem,
                                                                     _targetProject);

                    HemiContextSingleton.Instance.WorkItemsToMove.Add(moveInfo);
                }
            }
            #endregion
        }

        bool IMoveStage.Validate()
        {
            bool valid = true;
            StringBuilder builder = new StringBuilder();

            //
            // Did the user select a server?
            //
            if (HemiContextSingleton.Instance.TeamFoundationServer == null)
            {
                builder.AppendLine("Please choose a Team Foundation Server.");
                valid = false;
            }
            else
            {
                if (!HemiContextSingleton.Instance.TeamFoundationServer.HasAuthenticated)
                {
                    HemiContextSingleton.Instance.TeamFoundationServer.EnsureAuthenticated();
                }
            }

            //
            // Did the user select work items?
            //
            int workItemCount = 0;
            foreach (C1.Win.C1FlexGrid.Row row in _workItemsFlex.Rows)
            {
                if (row.Index != 0 && (bool)row["move"])
                {
                    workItemCount++;
                }
            }

            if (workItemCount == 0)
            {
                builder.AppendLine("Please select at least 1 Work Item to move.");
                valid = false;
            }

            //
            // Did the user select a target project?
            //
            if (_targetProject == null)
            {
                builder.AppendLine("Please select a target project.");
                valid = false;
            }

            if (!valid)
            {
                _invalidMessage = builder.ToString();
            }

            return valid;
        }

        #endregion

        private void _queryButton_Click(object sender, EventArgs e)
        {
            //
            // Pop up the query dialog
            //            
            if (_workItemPicker.ShowDialog() == DialogResult.OK)
            {
                ArrayList workItems = _workItemPicker.Control.SelectedWorkItems();

                ClearRows(_workItemsFlex);
                HemiContextSingleton.Instance.WorkItemsToMove.Clear();

                foreach (WorkItem workItem in workItems)
                {
                    C1.Win.C1FlexGrid.Row row = _workItemsFlex.Rows.Add();

                    row.UserData = workItem;
                    
                    row["id"] = workItem.Id;
                    row["title"] = workItem.Title;
                    row["move"] = true;
                    row["project"] = workItem.Project.Name;
                }
            }
        }

        private void ClearRows(C1.Win.C1FlexGrid.C1FlexGrid flex)
        {
            if (flex.Rows.Count > 0)
            {
                flex.Rows.RemoveRange(1, flex.Rows.Count - 1);
            }
        }
     
        #region Async get TFS Servers

        private void QueryForWorkItems_Load(object sender, EventArgs e)
        {
            GetRegisteredServers();
        }

        private void _srcRefresh_Click(object sender, EventArgs e)
        {
            GetRegisteredServers();
        }

        private void _tfsBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            //
            // Get a list of registered servers
            //
            _tfsComboBox.Items.Clear();
            _targetTfsCombo.Items.Clear();

            _tfsBackgroundWorker.ReportProgress(25, "Getting Registered Team Foundation Servers...");
            TeamFoundationServer[] registeredServers = RegisteredServers.GetServers();
            _tfsBackgroundWorker.ReportProgress(25, "Getting Registered Team Foundation Servers...");

            foreach (TeamFoundationServer tfs in registeredServers)
            {
                _tfsBackgroundWorker.ReportProgress(10, "Getting Registered Team Foundation Servers...");

                _tfsComboBox.Items.Add(tfs.Name);
                _targetTfsCombo.Items.Add(tfs.Name);
            }
        }

        private void _tfsBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {            
            _progressDialog.Close();
        }

        private void _tfsBackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            SafeUpdateProgress(e);
        }
        #endregion

        #region Async list projects for a TFS server

        private void _tfsComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            _projectBackgroundWorker.RunWorkerAsync();
            _progressDialog._progressLabel.Text = "Connecting to Team Foundation Server...";
            _progressDialog.ShowDialog();
        }

        private void _projectBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                string tfsName = (string)_tfsComboBox.Items[_tfsComboBox.SelectedIndex];

                //
                // The way we build the context (i.e. getting the work item store, ensuring
                // authentication, etc could be done inside of HemiContextSingleton, but
                // breaking it out this way makes it easier to report progress to the user.
                //
                UICredentialsProvider uiCreds = new UICredentialsProvider();

                _projectBackgroundWorker.ReportProgress(33, "Connecting to Team Foundation Server...");
                HemiContextSingleton.Instance.TeamFoundationServer = new TeamFoundationServer(tfsName, uiCreds);

                _projectBackgroundWorker.ReportProgress(33, "Authenticating...");
                HemiContextSingleton.Instance.TeamFoundationServer.EnsureAuthenticated();

                _projectBackgroundWorker.ReportProgress(37, "Getting Work Item Store...");
                HemiContextSingleton.Instance.WorkItemStore = (WorkItemStore)HemiContextSingleton.Instance.TeamFoundationServer.GetService(typeof(WorkItemStore));

                _workItemPicker = new WorkItemPicker();
                _workItemPicker.StartPosition = FormStartPosition.CenterParent;
            }
            catch
            {
                MessageBox.Show("Could not connect to Team Foundation Server", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                _projectBackgroundWorker.CancelAsync();
            }
        }

        private void _projectBackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            SafeUpdateProgress(e);
        }

        private void _projectBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            _progressDialog.Close();

            _targetTfsCombo.Enabled = true;
            _targetProjectCombo.Enabled = true;
            _targetTfsRefreshButton.Enabled = true;
        }
        #endregion

        private void GetRegisteredServers()
        {
            _tfsBackgroundWorker.RunWorkerAsync();
            _progressDialog._progressLabel.Text = "Getting Registered Team Foundation Servers...";
            _progressDialog.ShowDialog();
        }

        private void GetTargetProjects()
        {
            List<ProjectItem> targetProjects = new List<ProjectItem>();

            foreach (Project project in HemiContextSingleton.Instance.WorkItemStore.Projects)
            {
                targetProjects.Add(new ProjectItem(project));
            }

            _targetProjectCombo.DataSource = targetProjects;
        }

        private void _targetCombo_SelectedIndexChanged(object sender, EventArgs e)
        {
            ProjectItem projectItem = (ProjectItem)_targetProjectCombo.SelectedItem;
            _targetProject = projectItem.Project;
            MessageBox.Show("->" + _targetProject.Name);
        }

        private void SafeUpdateProgress(ProgressChangedEventArgs e)
        {
            _progressDialog._progressLabel.Text = e.UserState.ToString();

            int potentialUpdate = _progressDialog._progressBar.Value + e.ProgressPercentage;
            if (potentialUpdate < 100)
            {
                _progressDialog._progressBar.Value += e.ProgressPercentage;
            }
        }

        private void _targetTfsRefreshButton_Click(object sender, EventArgs e)
        {
            GetRegisteredServers();
        }

        private void _targetTfsCombo_SelectedIndexChanged(object sender, EventArgs e)
        {
            //
            // We don't need to do this async, because we already paid the init
            // start time to get here.
            //
            string tfsName = (string)_targetTfsCombo.Items[_targetTfsCombo.SelectedIndex];

            UICredentialsProvider uiCreds = new UICredentialsProvider();
            TeamFoundationServer targetTfs = new TeamFoundationServer(tfsName, uiCreds);
            
            targetTfs.EnsureAuthenticated();
            WorkItemStore targetWis = (WorkItemStore)targetTfs.GetService(typeof(WorkItemStore));

            List<ProjectItem> targetProjects = new List<ProjectItem>();

            foreach (Project project in targetWis.Projects)
            {
                targetProjects.Add(new ProjectItem(project));
            }

            _targetProjectCombo.DataSource = targetProjects;
        }
    }
}
